package com.mcp.converter.domain.rule.compatibility.function;

import com.mcp.converter.domain.checker.IncompatibilityDetail;
import com.mcp.converter.shared.response.sql.SQLElement;
import com.mcp.converter.domain.rule.compatibility.AbstractFunctionRule;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * 日期时间函数兼容性规则
 * OceanBase中日期时间函数的处理与Oracle有差异，特别是在时区处理方面
 * @author zengxiong
 */
public class DateTimeFunctionRule extends AbstractFunctionRule {

    private static final String RULE_ID = "FN001";
    private static final String RULE_NAME = "日期时间函数处理差异";
    private static final String RULE_DESCRIPTION = "OceanBase中日期时间函数的处理与Oracle存在差异，尤其是时区相关功能";

    private static final Set<String> DATETIME_FUNCTIONS = new HashSet<>(Arrays.asList("LOCALTIME"));

    public DateTimeFunctionRule() {
        super(RULE_ID, RULE_NAME, RULE_DESCRIPTION);
        setIncompatibilityDetail(
            "OceanBase中日期时间函数在以下方面与Oracle存在差异：\n" +
            "1. LOCALTIME函数：\n" +
            "   - OceanBase不支持该函数\n" +
            "   - Oracle的LOCALTIME返回会话时区时间\n" +
            "   - OceanBase需要显式转换时区",
                "OceanBase与Oracle在LOCALTIME函数上存在不兼容问题：\n" +
                        "1. Oracle的LOCALTIME返回会话时区时间，而OceanBase不支持该函数\n" +
                        "2. 直接迁移会导致SQL执行失败，报函数不存在错误\n" +
                        "3. 时间相关业务逻辑会出现偏差\n" +
                        "4. 定时任务可能无法按预期时间触发\n" +
                        "5. 时间戳比较操作会产生错误结果\n" +
                        "6. 报表统计的时间维度数据会不准确",
                "建议采取以下解决方案：\n" +
                        "1. 使用OceanBase等效函数CURRENT_TIMESTAMP替代\n" +
                        "2. 显式指定时区信息，如：CURRENT_TIMESTAMP AT TIME ZONE 'UTC'\n" +
                        "3. 避免在业务逻辑中直接使用LOCALTIME\n" +
                        "4. 对时间敏感的业务逻辑进行充分测试\n" +
                        "5. 考虑使用应用层处理时间转换\n" +
                        "6. 检查所有使用LOCALTIME的SQL语句\n" +
                        "7. 建立统一的时间处理规范",
            IncompatibilityDetail.Severity.HIGH
        );
    }

    @Override
    public boolean matches(Object target) {
        if (target instanceof SQLElement) {
            SQLElement element = (SQLElement) target;
            if (isFunctionElement(element)) {
                String functionName = element.getName().toUpperCase();
                return DATETIME_FUNCTIONS.contains(functionName);
            }
        }
        return false;
    }
    
    @Override
    public Set<String> getIncompatibleFunctions() {
        return new HashSet<>(DATETIME_FUNCTIONS);
    }
}
